<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram</title>
</head>
<body>
    <canvas id="physicsCanvas" width="600" height="400"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Configuration ---
        const cx = 150;
        const cy = canvas.height / 2;
        const R = 80;
        const startX = canvas.width;
        const curveStartX = 400;
        const arrowX = 480;

        // --- Styling ---
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        ctx.font = 'italic 24px "Times New Roman"';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // --- Helper Function to Draw Arrowheads ---
        function drawArrowhead(ctx, x, y, angle) {
            const headlen = 10;
            ctx.save();
            ctx.beginPath();
            ctx.translate(x, y);
            ctx.rotate(angle);
            ctx.moveTo(0, 0);
            ctx.lineTo(headlen, -headlen / 2);
            ctx.moveTo(0, 0);
            ctx.lineTo(headlen, headlen / 2);
            ctx.stroke();
            ctx.restore();
        }

        // --- 1. Draw the Star (Circle) ---
        ctx.beginPath();
        ctx.arc(cx, cy, R, 0, 2 * Math.PI);
        ctx.stroke();

        // --- 2. Draw the Radius Line and Label 'R' ---
        const radiusAngle = 2.4; // Angle in radians (approx 137 degrees)
        const radiusEndX = cx + R * Math.cos(radiusAngle);
        const radiusEndY = cy + R * Math.sin(radiusAngle);
        ctx.beginPath();
        ctx.moveTo(cx, cy);
        ctx.lineTo(radiusEndX, radiusEndY);
        ctx.stroke();
        ctx.fillText('R', cx + (R / 2) * Math.cos(radiusAngle) - 15, cy + (R / 2) * Math.sin(radiusAngle) + 5);

        // --- 3. Draw the Flow Lines ---
        // y_offsets from the center line for the top half. The bottom half is symmetric.
        const offsets = [R * 0.3, R * 0.75, R * 1.15];

        // Draw top 3 lines
        // Innermost (hits)
        let y_inner = cy - offsets[0];
        ctx.beginPath();
        ctx.moveTo(startX, y_inner);
        ctx.lineTo(curveStartX, y_inner);
        ctx.bezierCurveTo(cx + R * 0.8, y_inner, cx + R * 0.2, cy - R, cx, cy - R);
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_inner, Math.PI);

        // Middle (hits)
        let y_middle = cy - offsets[1];
        ctx.beginPath();
        ctx.moveTo(startX, y_middle);
        ctx.lineTo(curveStartX, y_middle);
        ctx.bezierCurveTo(cx + R, y_middle, cx, cy - R * 1.1, cx + R * Math.cos(2.4), cy + R * Math.sin(2.4));
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_middle, Math.PI);
        
        // Outermost (misses)
        let y_outer = cy - offsets[2];
        ctx.beginPath();
        ctx.moveTo(startX, y_outer);
        ctx.lineTo(curveStartX, y_outer);
        ctx.bezierCurveTo(cx + R * 1.5, y_outer, cx - R, cy - R * 1.8, cx - R * 0.8, cy - R * 1.2);
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_outer, Math.PI);

        // Draw bottom 3 lines (symmetrically)
        // Innermost (hits)
        y_inner = cy + offsets[0];
        ctx.beginPath();
        ctx.moveTo(startX, y_inner);
        ctx.lineTo(curveStartX, y_inner);
        ctx.bezierCurveTo(cx + R * 0.8, y_inner, cx + R * 0.2, cy + R, cx, cy + R);
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_inner, Math.PI);

        // Middle (hits)
        y_middle = cy + offsets[1];
        ctx.beginPath();
        ctx.moveTo(startX, y_middle);
        ctx.lineTo(curveStartX, y_middle);
        ctx.bezierCurveTo(cx + R, y_middle, cx, cy + R * 1.1, cx + R * Math.cos(-2.4), cy + R * Math.sin(-2.4));
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_middle, Math.PI);

        // Outermost (misses)
        y_outer = cy + offsets[2];
        ctx.beginPath();
        ctx.moveTo(startX, y_outer);
        ctx.lineTo(curveStartX, y_outer);
        ctx.bezierCurveTo(cx + R * 1.5, y_outer, cx - R, cy + R * 1.8, cx - R * 0.8, cy + R * 1.2);
        ctx.stroke();
        drawArrowhead(ctx, arrowX, y_outer, Math.PI);

        // --- 4. Draw Label 'V' ---
        ctx.fillText('V', curveStartX, cy - R * 1.15 - 30);

        // --- 5. Draw Bracket and Label 'b' ---
        const b_x = 550;
        const b_top_y = cy - offsets[2];
        const b_bottom_y = cy + offsets[2];
        const tick_size = 8;
        ctx.beginPath();
        // Vertical line
        ctx.moveTo(b_x, b_top_y);
        ctx.lineTo(b_x, b_bottom_y);
        // Top tick
        ctx.moveTo(b_x - tick_size / 2, b_top_y);
        ctx.lineTo(b_x + tick_size / 2, b_top_y);
        // Bottom tick
        ctx.moveTo(b_x - tick_size / 2, b_bottom_y);
        ctx.lineTo(b_x + tick_size / 2, b_bottom_y);
        ctx.stroke();
        ctx.fillText('b', b_x + 20, cy);

        // --- 6. Draw Figure Caption ---
        ctx.font = '20px "Times New Roman"';
        ctx.fillText('Fig. 1.88.', canvas.width / 2, canvas.height - 20);

    </script>
</body>
</html>